using System;
using System.Xml;
using System.Collections.Generic;
using Qyoto;
using Clandestine.Graphics;
using Clandestine.Graphics.Window;
using Clandestine.Engines.Field;

namespace Shlick
{
	public class MainWindow : QMainWindow
	{
		private Ui_MainWindow ui;
		private Dictionary<QWidget, int> Tabs = new Dictionary<QWidget, int>(); // dictionary to reverse lookup tab index >.>
		
		public event KeyPressEvent KeyPress;
		public event KeyReleaseEvent KeyRelease;
		
		public MainWindow ()
		{
			ui = new Ui_MainWindow();
			ui.SetupUi(this);
			
			// Actions
			Connect(this.ui.tabWidget, SIGNAL("tabCloseRequested(int)"), this, SLOT("OnTabCloseRequest(int)"));
			Connect(this.ui.actionNew, SIGNAL("triggered()"), this, SLOT("OnActionNew()"));
			Connect(this.ui.actionOpen, SIGNAL("triggered()"), this, SLOT("OnActionOpen()"));
			Connect(this.ui.actionUndo, SIGNAL("triggered()"), this, SLOT("OnActionUndo()"));
			Connect(this.ui.actionRedo, SIGNAL("triggered()"), this, SLOT("OnActionRedo()"));	
			Connect(this.ui.actionRun, SIGNAL("triggered()"), this, SLOT("OnActionRun()"));
			Connect(this.ui.actionStop, SIGNAL("triggered()"), this, SLOT("OnActionStop()"));
			
			// Debuggg
			this.OpenMap("maps/example-map.xml");
		}
		
		protected override void KeyPressEvent (QKeyEvent arg1)
		{
			if (KeyPress != null)
				KeyPress(arg1.Key());
		}
		
		protected override void KeyReleaseEvent (QKeyEvent arg1)
		{
			if (KeyRelease != null)
				KeyRelease(arg1.Key());
		}
		
		#region Events From Tabs (Rename/Close etc.)

		public void UpdateTabTitle(QWidget tab, string text)
		{
			lock (Tabs)
			{
				if (!this.Tabs.ContainsKey(tab))
					throw new Exception("Trying to update the title of a tab we don't even have!");

				this.ui.tabWidget.SetTabText(this.Tabs[tab], text);
			}
		}
		
		public void CloseTab(QWidget tab)
		{
			lock (Tabs)
			{
				if (!this.Tabs.ContainsKey(tab))
					throw new Exception("Trying to close a tab that we don't even have!");
				int index = this.Tabs[tab];
				
				// Remove
				this.ui.tabWidget.RemoveTab(index);
				this.Tabs.Remove(tab);
				
				// select another tab, if there are any!
				if (this.ui.tabWidget.Count > 0)
					this.ui.tabWidget.SetCurrentIndex((index == 0) ? index + 1 : index - 1);
			}
		}
		
		#endregion
		
		#region Slots
		
		// when the x of a tab is clicked
		[Q_SLOT("OnTabCloseRequest(int)")]
		protected void OnTabCloseRequest(int index)
		{
			// switch to it
			this.ui.tabWidget.SetCurrentIndex(index);
		
			// pass to the tab so they can prompt user etc.
			((MapDocument)this.ui.tabWidget.Widget(index)).CloseRequested();
		}
		
		[Q_SLOT("OnActionNew()")]
		protected void OnActionNew()
		{
			this.NewMap();
		}

		[Q_SLOT("OnActionOpen()")]
		protected void OnActionOpen()
		{
			this.OpenMap();
		}
		
		[Q_SLOT("OnActionUndo()")]
		protected void OnActionUndo()
		{
			((MapDocument)this.ui.tabWidget.Widget(this.ui.tabWidget.CurrentIndex)).Undo();
		}
		
		[Q_SLOT("OnActionRedo()")]
		protected void OnActionRedo()
		{
			((MapDocument)this.ui.tabWidget.Widget(this.ui.tabWidget.CurrentIndex)).Redo();
		}
		
		[Q_SLOT("OnActionRun()")]
		protected void OnActionRun()
		{
			((MapDocument)this.ui.tabWidget.Widget(this.ui.tabWidget.CurrentIndex)).Run();
		}
		
		[Q_SLOT("OnActionStop()")]
		protected void OnActionStop()
		{
			((MapDocument)this.ui.tabWidget.Widget(this.ui.tabWidget.CurrentIndex)).Stop();
		}
		
		#endregion
		
		#region New/Open/Close
		
		public void NewMap()
		{
			// Make tab
			MapDocument tab = new MapDocument();
			
			this.AddTab(tab);
		}
		
		public void OpenMap()
		{
			string filename = QFileDialog.GetOpenFileName(this, "Open Map", "", "Maps (*.xml)");
			
			if (string.IsNullOrEmpty(filename))
				return; // cancel selected
			
			this.OpenMap(filename);
		}
		public void OpenMap(string filename)
		{
			// Make tab
			MapDocument tab = new MapDocument(filename);		
			
			this.AddTab(tab);
		}
		
		private void AddTab(QWidget tab)
		{
			// Events
			((MapDocument)tab).TabTitleChanged += new TabTitleChanged(UpdateTabTitle);
			((MapDocument)tab).CloseTab += new CloseTab(CloseTab);
		
			// Add to TabWidget and remember index
			lock (this.Tabs) // messy race condition >.>
				this.Tabs.Add(tab, ui.tabWidget.AddTab(tab, ""));
			
			// Switch to it
			ui.tabWidget.SetCurrentIndex(this.Tabs[tab]);
		}
		
		#endregion
	}
}

